Types
Type Inference
-
Equivalent:
let hello = 'hi mom' let hello: String = 'hi mom'
Value Type
-
It's a type whose value is copied when it’s assigned to a variable or constant, or when it’s passed to a function.
-
Value Types :
-
Integers
-
Floating-point numbers
-
Booleans
-
Strings
-
Arrays
-
Dictionaries
-
Structs
-
All basic types are implemented as structures behind the scenes.
-
-
Enums
-
-
Ex1 :
struct Resolution { var width = 0 var height = 0 } let hd = Resolution(width: 1920, height: 1080) var cinema = hd-
Because
Resolutionis a structure, a copy of the existing instance is made, and this new copy is assigned tocinema. Even thoughhdandcinemanow have the same width and height, they’re two completely different instances behind the scenes.
-
Reference Types
-
Reference types are not copied when they’re assigned to a variable or constant, or when they’re passed to a function. Rather than a copy, a reference to the same existing instance is used.
-
Reference Types :
-
Classes
-
-
Ex1 :
let tenEighty = VideoMode()
tenEighty.resolution = hd
tenEighty.interlaced = true
tenEighty.name = "1080i"
tenEighty.frameRate = 25.0
let alsoTenEighty = tenEighty
alsoTenEighty.frameRate = 30.0
print("The frameRate property of tenEighty is now \(tenEighty.frameRate)")
// Prints "The frameRate property of tenEighty is now 30.0". Both are 30.0.
Booleans
let orangesAreOrange = true
let turnipsAreDelicious = false
-
Not allowed :
let i = 1 if i { // this example will not compile, and will report an error } -
Allowed :
let i = 1 if i == 1 { // this example will compile successfully }
Numbers
Int
-
Types :
-
Int8 -
Int16 -
Int32 -
Int64 -
UInt8 -
UInt16 -
UInt32 -
UInt64
-
-
Generic :
-
In most cases, you don’t need to pick a specific size of integer to use in your code. Swift provides an additional integer type,
Int/UInt, which has the same size as the current platform’s native word size:-
On a 32-bit platform:
-
Int/UIntis the same size asInt32/UInt32.
-
-
On a 64-bit platform:
-
Int/UIntis the same size asInt64/UInt64.
-
-
-
Unless you need to work with a specific size of integer, always use
Intfor integer values in your code. This aids code consistency and interoperability. -
Even on 32-bit platforms,
Intcan store any value between-2,147,483,648and2,147,483,647, and is large enough for many integer ranges. -
Note about UInt :
-
Use
UIntonly when you specifically need an unsigned integer type with the same size as the platform’s native word size. If this isn’t the case,Intis preferred, even when the values to be stored are known to be nonnegative. A consistent use ofIntfor integer values aids code interoperability, avoids the need to convert between different number types, and matches integer type inference, as described in Type Safety and Type Inference .
-
-
-
Bounds :
-
UInt8.min -
UInt8.max
-
Float
-
Represents a 32-bit floating-point number.
-
Can have a precision as little as 6 decimal digits.
Double
-
Represents a 64-bit floating-point number.
-
Has a precision of at least 15 decimal digits.
-
In situations where either type would be appropriate,
Doubleis preferred.
Numeric Literals
let decimalInteger = 17
let binaryInteger = 0b10001 // 17 in binary notation
let octalInteger = 0o21 // 17 in octal notation
let hexadecimalInteger = 0x11 // 17 in hexadecimal notation
-
Decimals:
-
1.25e2means 1.25 x 10², or125.0. -
1.25e-2means 1.25 x 10⁻², or0.0125.
-
-
Hexadecimals:
-
0xFp2means 15 x 2², or60.0. -
0xFp-2means 15 x 2⁻², or3.75.
-
Formatting
let paddedDouble = 000123.456
let oneMillion = 1_000_000
let justOverOneMillion = 1_000_000.000_000_1
String
Literals
-
Singleline :
let someString = "Some string literal value" -
Multiline :
let quotation = """ The White Rabbit put on his spectacles. "Where shall I begin, please your Majesty?" he asked. "Begin at the beginning," the King said gravely, "and go on till you come to the end; then stop." """let singleLineString = "These are the same." let multilineString = """ These are the same. """let softWrappedQuotation = """ The White Rabbit put on his spectacles. "Where shall I begin, \ please your Majesty?" he asked. "Begin at the beginning," the King said gravely, "and go on \ till you come to the end; then stop." """-
If you’re using multiline string literals to build up the lines of a longer string, you want every line in the string to end with a line break, including the last line.
let badStart = """ one two """ let end = """ three """ print(badStart + end) // Prints two lines: // one // twothree let goodStart = """ one two """ print(goodStart + end) // Prints three lines: // one // two // three
-
Concatenation
"hello, " + "world" // equals "hello, world"
Interpolation
let multiplier = 3
let message = "\(multiplier) times 2.5 is \(Double(multiplier) * 2.5)"
// message is "3 times 2.5 is 7.5"
Chars
for character in "Dog!🐶" {
print(character)
}
let exclamationMark: Character = "!"
let catCharacters: [Character] = ["C", "a", "t", "!", "🐱"]
let catString = String(catCharacters)
print(catString)
// Prints "Cat!🐱"
Special Chars
-
\0(null character) -
\\(backslash) -
\t(horizontal tab) -
\n(line feed) -
\r(carriage return) -
\"(double quotation mark) -
\'(single quotation mark) -
\u{n}, where n is a 1–8 digit hexadecimal number. -
How to avoid using special chars :
print(#"Write an interpolated string in Swift using \(multiplier)."#) // Prints "Write an interpolated string in Swift using \(multiplier)."let threeMoreDoubleQuotationMarks = #""" Here are three more double quotes: """ "\""# // remove the backslash
Manipulation
-
Length:
let unusualMenagerie = "Koala 🐨, Snail 🐌, Penguin 🐧, Dromedary 🐪" print("unusualMenagerie has \(unusualMenagerie.count) characters") // Prints "unusualMenagerie has 40 characters" -
Insert and Remove:
var welcome = "hello" welcome.insert("!", at: welcome.endIndex) // welcome now equals "hello!" welcome.insert(contentsOf: " there", at: welcome.index(before: welcome.endIndex)) // welcome now equals "hello there!" -
Subranges:
welcome.remove(at: welcome.index(before: welcome.endIndex)) // welcome now equals "hello there" let range = welcome.index(welcome.endIndex, offsetBy: -6)..<welcome.endIndex welcome.removeSubrange(range) // welcome now equals "hello" -
Substrings:
let greeting = "Hello, world!" let index = greeting.firstIndex(of: ",") ?? greeting.endIndex let beginning = greeting[..<index] // beginning is "Hello" // Convert the result to a String for long-term storage. let newString = String(beginning) -
Prefixes:
let romeoAndJuliet = [ "Act 1 Scene 1: Verona, A public place", "Act 1 Scene 2: Capulet's mansion", "Act 1 Scene 3: A room in Capulet's mansion", ] // PREFIX var act1SceneCount = 0 for scene in romeoAndJuliet { if scene.hasPrefix("Act 1 ") { act1SceneCount += 1 } } print("There are \(act1SceneCount) scenes in Act 1") // Prints "There are 5 scenes in Act 1" // SUFFIX var mansionCount = 0 var cellCount = 0 for scene in romeoAndJuliet { if scene.hasSuffix("Capulet's mansion") { mansionCount += 1 } else if scene.hasSuffix("Friar Lawrence's cell") { cellCount += 1 } } print("\(mansionCount) mansion scenes; \(cellCount) cell scenes") // Prints "6 mansion scenes; 2 cell scenes"
Tuples
Creation
-
Tuples group multiple values into a single compound value.
-
The values within a tuple can be of any type and don’t have to be of the same type as each other.
let http404Error = (404, "Not Found") // http404Error is of type (Int, String), and equals (404, "Not Found") -
If you name the elements in a tuple, you can use the element names to access the values of those elements:
let http200Status = (statusCode: 200, description: "OK") -
Tuples are particularly useful as the return values of functions. A function that tries to retrieve a web page might return the
(Int, String)tuple type to describe the success or failure of the page retrieval. By returning a tuple with two distinct values, each of a different type, the function provides more useful information about its outcome than if it could only return a single value of a single type.
Access
-
Index :
print("The status code is \(http404Error.0)") // Prints "The status code is 404" print("The status message is \(http404Error.1)") // Prints "The status message is Not Found" -
Name (if defined):
print("The status code is \(http200Status.statusCode)") // Prints "The status code is 200" print("The status message is \(http200Status.description)") // Prints "The status message is OK" -
Destructuring / Decomposition :
let (statusCode, statusMessage) = http404Error print("The status code is \(statusCode)") // Prints "The status code is 404" print("The status message is \(statusMessage)") // Prints "The status message is Not Found"-
If you only need some of the tuple’s values, ignore parts of the tuple with an underscore (
_) when you decompose the tuple:let (justTheStatusCode, _) = http404Error print("The status code is \(justTheStatusCode)") // Prints "The status code is 404"
-
Logical Comparisons in Tuples
-
You can compare two tuples if they have the same type and the same number of values. Tuples are compared from left to right, one value at a time, until the comparison finds two values that aren’t equal.
(1, "zebra") < (2, "apple") // true because 1 is less than 2; "zebra" and "apple" aren't compared
(3, "apple") < (3, "bird") // true because 3 is equal to 3, and "apple" is less than "bird"
(4, "dog") == (4, "dog") // true because 4 is equal to 4, and "dog" is equal to "dog"
Arrays
Creation
var someInts: [Int] = []
print("someInts is of type [Int] with \(someInts.count) items.")
// Prints "someInts is of type [Int] with 0 items."
var threeDoubles = Array(repeating: 0.0, count: 3)
// threeDoubles is of type [Double], and equals [0.0, 0.0, 0.0]
var sixDoubles = threeDoubles + anotherThreeDoubles
-
New array of Strings, via the content of a Dictionary:
let airportCodes = [String](airports.keys) // airportCodes is ["LHR", "YYZ"] let airportNames = [String](airports.values) // airportNames is ["London Heathrow", "Toronto Pearson"]
Access
var firstItem = shoppingList[0]
// firstItem is equal to "Eggs"
Modification
-
You can use subscript syntax to change an existing value at a given index:
shoppingList[0] = "Six eggs"
// the first item in the list is now equal to "Six eggs" rather than "Eggs"
shoppingList[4...6] = ["Bananas", "Apples"]
// shoppingList now contains 6 items
Insert
-
Via
append:shoppingList.append("Flour") // shoppingList now contains 3 items, and someone is making pancakes -
Via
insert:shoppingList.insert("Maple Syrup", at: 0) // shoppingList now contains 7 items // "Maple Syrup" is now the first item in the list -
Via
+=:shoppingList += ["Baking Powder"] // shoppingList now contains 4 items shoppingList += ["Chocolate Spread", "Cheese", "Butter"] // shoppingList now contains 7 items
Remove
-
Via
remove:let mapleSyrup = shoppingList.remove(at: 0) // the item that was at index 0 has just been removed // shoppingList now contains 6 items, and no Maple Syrup // the mapleSyrup constant is now equal to the removed "Maple Syrup" string -
removeLast.
Other common methods
-
isEmpty
Set
-
A set stores distinct values of the same type in a collection with no defined ordering.
-
Uses :
-
You can use a set instead of an array when the order of items isn’t important
-
Or when you need to ensure that an item only appears once .
-
-
My interpretation :
-
It's a "dictionary that only has keys, no values" .
-
Creation
var letters = Set<Character>()
print("letters is of type Set<Character> with \(letters.count) items.")
// Prints "letters is of type Set<Character> with 0 items."
var favoriteGenres: Set<String> = ["Rock", "Classical", "Hip hop"]
// favoriteGenres has been initialized with three initial items
var favoriteGenres: Set = ["Rock", "Classical", "Hip hop"]
Modification
letters.insert("a")
// letters now contains 1 value of type Character
letters = []
// letters is now an empty set, but is still of type Set<Character>
Operations
-
Use the
intersection(_:)method to create a new set with only the values common to both sets. -
Use the
symmetricDifference(_:)method to create a new set with values in either set, but not both. -
Use the
union(_:)method to create a new set with all of the values in both sets. -
Use the
subtracting(_:)method to create a new set with values not in the specified set.
Logic
-
Contains :
if favoriteGenres.contains("Funk") {
print("I get up on the good foot.")
} else {
print("It's too funky in here.")
}
// Prints "It's too funky in here."
-
Use the “is equal” operator (
==) to determine whether two sets contain all of the same values. -
Use the
isSubset(of:)method to determine whether all of the values of a set are contained in the specified set. -
Use the
isSuperset(of:)method to determine whether a set contains all of the values in a specified set. -
Use the
isStrictSubset(of:)orisStrictSuperset(of:)methods to determine whether a set is a subset or superset, but not equal to, a specified set. -
Use the
isDisjoint(with:)method to determine whether two sets have no values in common.
Dictionary
Creation
var namesOfIntegers: [Int: String] = [:]
// namesOfIntegers is an empty [Int: String] dictionary
namesOfIntegers[16] = "sixteen"
// namesOfIntegers now contains 1 key-value pair
namesOfIntegers = [:]
// namesOfIntegers is once again an empty dictionary of type [Int: String]
var airports: [String: String] = ["YYZ": "Toronto Pearson", "DUB": "Dublin"]
var airports = ["YYZ": "Toronto Pearson", "DUB": "Dublin"]
Modification
-
Insert / Modify :
airports["LHR"] = "London" // the airports dictionary now contains 3 items -
Remove :
airports["APL"] = nil // APL has now been removed from the dictionary -
updateValue-
Returns the old value after performing an update.
if let oldValue = airports.updateValue("Dublin Airport", forKey: "DUB") { print("The old value for DUB was \(oldValue).") } // Prints "The old value for DUB was Dublin." -
-
removeValue-
Removes the key-value pair if it exists and returns the removed value, or returns
nilif no value existed
if let removedValue = airports.removeValue(forKey: "DUB") { print("The removed airport's name is \(removedValue).") } else { print("The airports dictionary doesn't contain a value for DUB.") } // Prints "The removed airport's name is Dublin Airport." -
Optionals
-
An optional represents two possibilities: Either there is a value of a specified type, and you can unwrap the optional to access that value, or there isn’t a value at all.
Creation
-
To write an optional type, you write a question mark (
?) after the name of the type that the optional contains.-
For example, the type of an optional
IntisInt?.
-
let possibleNumber = "123"
let convertedNumber = Int(possibleNumber)
// As the conversion `Int()` can't always be made, the returned type for convertedNumber is "optional Int".
Nil
var serverResponseCode: Int? = 404
// serverResponseCode contains an actual Int value of 404
serverResponseCode = nil
// serverResponseCode now contains no value
Default with
?
-
If you define an optional variable without providing a default value, the variable is automatically set to
nil:
var surveyAnswer: String?
// surveyAnswer is automatically set to nil
What to do when it is
nil
-
Skip the code that operates on the value when it’s
nil. -
? Propagate the
nilvalue, by returningnilor using the?.operator described in Optional Chaining . -
Provide a fallback value, using the
??operator. -
Stop program execution, using the
!operator.